package com.petRescueCenter.demo.posting.entity.dto;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.springframework.data.jpa.domain.Specification;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.petRescueCenter.demo.common.enumPackage.LockedEmun;
import com.petRescueCenter.demo.common.enumPackage.pTypeEmun;
import com.petRescueCenter.demo.posting.entity.Posting;
import com.petRescueCenter.demo.user.entity.User;

import io.swagger.annotations.ApiModelProperty;

public class PostingQueryDTO {
	@ApiModelProperty(name = "id", value = "帖子id", required = false)
	private Long id;
	@ApiModelProperty(name = "authorId", value = "作者id", required = false)
	private Long authorId;
	@ApiModelProperty(name = "authorName", value = "作者名字", required = false)
	private String authorName;
	@ApiModelProperty(name = "type", value = "类型", required = false)
	private String type;
	@ApiModelProperty(name = "CreateTimeStart", value = "要查询的创建时间范围的开始", required = false)
	private Date CreateTimeStart;
	@ApiModelProperty(name = "CreateTimeEnd", value = "要查询的创建时间范围的结束", required = false)
	private Date CreateTimeEnd;
	// 通過用戶找到他關注的帖子
	@ApiModelProperty(name = "userId", value = "用户id", required = false)
	private Long userId;
	private Long[] ids;
	private String state;
	private Long fansId;

	public Long getFansId() {
		return fansId;
	}

	public void setFansId(Long fansId) {
		this.fansId = fansId;
	}

	public Long getId() {
		return id;
	}

	public Long getAuthorId() {
		return authorId;
	}

	public String getAuthorName() {
		return authorName;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	@Temporal(TemporalType.TIMESTAMP)
	@JsonFormat(pattern = "yyyy/MM/dd HH:mm:ss", timezone = "GMT+8")
	public Date getCreateTimeStart() {
		return CreateTimeStart;
	}

	public Long[] getIds() {
		return ids;
	}

	public void setIds(Long[] ids) {
		this.ids = ids;
	}

	@Temporal(TemporalType.TIMESTAMP)
	@JsonFormat(pattern = "yyyy/MM/dd HH:mm:ss", timezone = "GMT+8")
	public Date getCreateTimeEnd() {
		return CreateTimeEnd;
	}

	public void setCreateTimeStart(Date createTimeStart) {
		CreateTimeStart = createTimeStart;
	}

	public void setCreateTimeEnd(Date createTimeEnd) {
		CreateTimeEnd = createTimeEnd;
	}

	public void setAuthorId(Long authorId) {
		this.authorId = authorId;
	}

	public void setAuthorName(String authorName) {
		this.authorName = authorName;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public Long getUserId() {
		return userId;
	}

	public void setUserId(Long userId) {
		this.userId = userId;
	}

	@SuppressWarnings({ "serial" })
	public static Specification<Posting> getWhereClause(final PostingQueryDTO postingQueryDTO) {
		return new Specification<Posting>() {
			@Override
			public Predicate toPredicate(Root<Posting> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				List<Predicate> predicate = new ArrayList<>();

				if (null != postingQueryDTO.getId()) {
					predicate.add(criteriaBuilder.equal(root.get("id").as(Long.class), postingQueryDTO.getId()));
				}
				if (null != postingQueryDTO.getIds()) {
					List<Predicate> ps = new ArrayList<Predicate>();
					for (Long id : postingQueryDTO.getIds()) {
						ps.add(criteriaBuilder.equal(root.get("id").as(Long.class), id));
					}
					predicate.add(criteriaBuilder.or(ps.toArray(new Predicate[ps.size()])));
				}
				if (null != postingQueryDTO.getAuthorId()) {
					Join<Posting, User> join = root.join("author", JoinType.LEFT);
					predicate.add(criteriaBuilder.equal(join.get("id").as(Long.class), postingQueryDTO.getAuthorId()));
				}
				if (null != postingQueryDTO.getUserId()) {
					Join<Posting, User> join = root.join("fans", JoinType.LEFT);
					predicate.add(criteriaBuilder.equal(join.get("id").as(Long.class), postingQueryDTO.getUserId()));
				}
				if (StringUtils.isNotBlank(postingQueryDTO.getAuthorName())) {
					Join<Posting, User> join = root.join("author", JoinType.LEFT);
					predicate.add(criteriaBuilder.like(join.get("name").as(String.class),
							"%" + postingQueryDTO.getAuthorName() + "%"));
				}
				if (StringUtils.isNotBlank(postingQueryDTO.getState())) {
					if (postingQueryDTO.getState().equals("NO")) {
						predicate.add(criteriaBuilder.equal(root.get("state").as(LockedEmun.class), LockedEmun.NO));
					} else {
						predicate.add(criteriaBuilder.equal(root.get("state").as(LockedEmun.class), LockedEmun.YES));
					}
				}
				if (null != postingQueryDTO.getCreateTimeStart()) {
					predicate.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(Date.class),
							postingQueryDTO.getCreateTimeStart()));
				}
				if (null != postingQueryDTO.getCreateTimeEnd()) {
					predicate.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime").as(Date.class),
							postingQueryDTO.getCreateTimeEnd()));
				}
				if (StringUtils.isNotBlank(postingQueryDTO.getType())) {
					if (postingQueryDTO.getType().equals("文章")) {
						predicate.add(criteriaBuilder.equal(root.get("type").as(pTypeEmun.class), pTypeEmun.POSTING));
					} else if (postingQueryDTO.getType().equals("失宠招领")) {
						predicate.add(criteriaBuilder.equal(root.get("type").as(pTypeEmun.class), pTypeEmun.FINDO));
					} else if (postingQueryDTO.getType().equals("寻宠启示")) {
						predicate.add(criteriaBuilder.equal(root.get("type").as(pTypeEmun.class), pTypeEmun.FINDP));
					} else {
						predicate.add(criteriaBuilder.equal(root.get("type").as(pTypeEmun.class), pTypeEmun.WARING));
					}
				}

				Predicate[] pre = new Predicate[predicate.size()];
				return query.where(predicate.toArray(pre)).getRestriction();
			}
		};
	}
}
